#pragma warning (disable:4786)

#include "Message.h"
#include "Block.h"
#include "Demo.h"
#include <ace/OS.h>


bool g_IsRecamming = true;
extern bool g_Intermission;
bool g_ChangeModels = false;
int g_NewModels = 500;
int g_Weapon;

int g_CurrentEntity = 0;

std::vector<std::string> g_Models;
int	g_ModelsMapping[3][500];
int g_DemoNum;

bool Message::UsingRealTime = false;


Message::~Message()
{
}

Message* Message::LoadMessage(const Block& B)
{
	Message* pMessage = NULL;
	byte ID = B.GetByte();
	switch (ID)
	{
	case MSG_BAD:
		pMessage = new MessageBad(B);
		break;
	case MSG_NOP:
		pMessage = new MessageNOP(B);
		break;
	case MSG_DISCONNECT:
		pMessage = new MessageDisconnect(B);
		break;
	case MSG_UPDATESTAT: 
		pMessage = new MessageUpdatestat(B);
		break;
	case MSG_VERSION: 
		pMessage = new MessageVersion(B);
		break;
	case MSG_SETVIEW: 
		pMessage = new MessageSetView(B);
		break;
	case MSG_SOUND: 
		pMessage = new MessageSound(B);
		break;
	case MSG_TIME: 
		pMessage = new MessageTime(B);
		break;
	case MSG_PRINT: 
		pMessage = new MessagePrint(B);
		break;
	case MSG_STUFFTEXT: 
		pMessage = new MessageStufftext(B);
		break;
	case MSG_SETANGLES: 
		pMessage = new MessageSetangles(B);
		if (g_IsRecamming)
		{
			delete pMessage;
			pMessage = NULL;
		}
		break;
	case MSG_SERVERINFO: 
		pMessage = new MessageServerinfo(B);
		break;
	case MSG_LIGHTSTYLE:
		pMessage = new MessageLightstyle(B);
		break;
	case MSG_UPDATENAME: 
		pMessage = new MessageUpdatename(B);
		break;
	case MSG_UPDATEFRAGS: 
		pMessage = new MessageUpdatefrags(B);
		break;
	case MSG_CLIENTDATA: 
		pMessage = new MessageClientdata(B);
		break;
	case MSG_STOPSOUND: 
		pMessage = new MessageStopsound(B);
		break;
	case MSG_UPDATECOLOR: 
		pMessage = new MessageUpdateColor(B);
		break;
	case MSG_PARTICLE: 
		pMessage = new MessageParticle(B);
		break;			
	case MSG_DAMAGE: 
		pMessage = new MessageDamage(B);	
		break;
	case MSG_SPAWNSTATIC: 
		pMessage = new MessageSpawnstatic(B);
		break;
	case MSG_SPAWNBINARY: 
		pMessage = new MessageSpawnbinary(B);
		break;
	case MSG_SPAWNBASELINE: 
		pMessage = new MessageSpawnBaseLine(B);
		break;
	case MSG_TEMPENTITY: 
		pMessage = new MessageTempEntity(B);
		break;
	case MSG_SETPAUSE: 
		pMessage = new MessageSetpause(B);
		break;
	case MSG_SIGHNONUP: 
		pMessage = new MessageSignonUp(B);
		break;
	case MSG_CENTERPRINT: 
		pMessage = new MessageCenterprint(B);
		break;
	case MSG_KILLEDMONSTER: 
		pMessage = new MessageKilledmonster(B);
		break;
	case MSG_FOUNDSECRET: 
		pMessage = new MessageFoundSecret(B);
		break;
	case MSG_SPAWNSTATICSOUND: 
		pMessage = new MessageSpawnstatSound(B);
		break;
	case MSG_INTERMISSION: 
		pMessage = new MessageIntermission(B);
		break;
	case MSG_FINALE: 
		pMessage = new MessageFinale(B);
		break;
	case MSG_CDTRACK: 
		pMessage = new MessageCDtrack(B);
		break;
	case MSG_SELLSCREEN: // sellscreen
		pMessage = new MessageSellscreen(B);
		break;
	default: // updateentity
		pMessage = new MessageUpdateEntity(B,ID);
		break;
	}

/*	if (!pMessage)
		throw "Error - pMessage==NULL";*/
	
	return pMessage; 
}

///////////////////////////////////////
MessageVoid::MessageVoid(const Buffer& B) : Message(B)
{
}

void MessageVoid::WriteTo(Buffer& B)
{
	B.PutByte(GetMsgId());
}


///////////////////////////////////////
MessageByte::MessageByte(const Buffer& B) : Message(B)
{
	m_Value = B.GetByte();
}
void MessageByte::WriteTo(Buffer& B)
{
	B.PutByte(GetMsgId());
	B.PutByte(m_Value);
}


///////////////////////////////////////
MessageShort::MessageShort(const Buffer& B) : Message(B)
{
	m_Value = B.GetShort();
}
void MessageShort::WriteTo(Buffer& B)
{
	B.PutByte(GetMsgId());
	B.PutShort(m_Value);
}


///////////////////////////////////////
MessageLong::MessageLong(const Buffer& B) : Message(B)
{
	m_Value = B.GetLong();

}
void MessageLong::WriteTo(Buffer& B)
{
	B.PutByte(GetMsgId());
	B.PutLong(m_Value);
}

///////////////////////////////////////
MessageByteByte::MessageByteByte(const Buffer& B) : Message(B)
{
	m_First = B.GetByte();
	m_Second = B.GetByte();

}
void MessageByteByte::WriteTo(Buffer& B)
{
	B.PutByte(GetMsgId());
	B.PutByte(m_First);
	B.PutByte(m_Second);
}

///////////////////////////////////////
MessageByteShort::MessageByteShort(const Buffer& B) : Message(B)
{
	m_First = B.GetByte();
	m_Second = B.GetShort();

}
void MessageByteShort::WriteTo(Buffer& B)
{
	B.PutByte(GetMsgId());
	B.PutByte(m_First);
	B.PutShort(m_Second);
}

///////////////////////////////////////
MessageText::MessageText(const Buffer& B) : Message(B)
{
	m_Data = B.GetString();
}

void MessageText::WriteTo(Buffer& B)
{
	B.PutByte(GetMsgId());
	B.PutString(m_Data);
}

///////////////////////////////////////
MessageByteString::MessageByteString(const Buffer& B) : Message(B)
{
	m_Id = B.GetByte();
	m_Text = B.GetString();
}

void MessageByteString::WriteTo(Buffer& B)
{
	B.PutByte(GetMsgId());
	B.PutByte(m_Id);
	B.PutString(m_Text);
}


///////////////////////////////////////
template <int Size>
MessageRawData<Size>::MessageRawData(const Buffer& B) : Message(B)
{
	for (int I = 0; I < Size; I++)
		m_Data[I] = B.GetByte();
}

template <int Size>
void MessageRawData<Size>::WriteTo(Buffer& B)
{
	B.PutByte(GetMsgId());
	for (int I = 0; I < Size; I++)
		B.PutByte(m_Data[I]);
}


///////////////////////////////////////
MessageUpdatestat::MessageUpdatestat(const Buffer& B) : Message(B)
{
	m_Index = B.GetByte();
	m_Value = B.GetLong();
}

void MessageUpdatestat::WriteTo(Buffer& B)
{
	B.PutByte(MSG_UPDATESTAT);

	B.PutByte(m_Index);
	B.PutLong(m_Value);
}



MessageSound::MessageSound(const Buffer& B) : Message(B)
{
	m_Mask = B.GetByte();
	if 	(m_Mask & SND_VOLUME)
		m_Vol = B.GetByte();
	else
		m_Vol = 255;
	if (m_Mask & SND_ATTENUATION)
		m_Att = B.GetByte();
	else
		m_Att = 64;
	
	for (int I = 0; I < 9; I++)
		m_Data[I] = B.GetByte();
}

void MessageSound::WriteTo(Buffer& B)
{
	B.PutByte(MSG_SOUND);
	B.PutByte(m_Mask);
	if 	(m_Mask & SND_VOLUME)
		B.PutByte(m_Vol);
	if (m_Mask & SND_ATTENUATION)
		B.PutByte(m_Att);
	
	for (int I = 0; I < 9; I++)
		B.PutByte(m_Data[I]);
}

MessageTime::MessageTime(const Block& B) : Message(B)
{
	m_Time = B.GetFloat();
	B.SetBlockTime(m_Time);
}

void MessageTime::WriteTo(Buffer& B)
{
	B.PutByte(MSG_TIME);
	if (Message::UsingRealTime)
	{
		B.PutFloat(m_Time);
	}
	else
	{
		static ACE_Time_Value LastUsedTime = ACE_OS::gettimeofday();
		static float TimeToWrite = 1.4f;
//		TimeToWrite += 0.05f;

		ACE_Time_Value Curr = ACE_OS::gettimeofday();
		int MSec = (Curr-LastUsedTime).msec();
		if (MSec > 0)
			TimeToWrite += (MSec / 1000.0);
		LastUsedTime = Curr;
		
		B.PutFloat(TimeToWrite);
	}

}


MessageSetangles::MessageSetangles(const Buffer& B) : Message(B)
{
	for (int I = 0; I < 3; I++)
		m_Angles[I] = B.GetByte();
}

void MessageSetangles::WriteTo(Buffer& B)
{
	B.PutByte(MSG_SETANGLES);
	for (int I = 0; I < 3; I++)
		B.PutByte(m_Angles[I]);
}

MessageServerinfo::MessageServerinfo(const Buffer& B) : Message(B)
{
	m_Serverversion = B.GetLong();
	m_MaxClients = B.GetByte();
	m_Multi = B.GetByte();
	m_MapName = B.GetString();

	std::string Temp;
	
	int I = 1;
	Temp = B.GetString();
	while (Temp.length())
	{
		int Ind= -1;
		for (int J = 0; J < g_Models.size(); J++)
		{
			if (g_Models[J] == Temp)
			{
				Ind = J; 
				break;
			}
		}
		if (Ind == -1)
		{
			g_Models.push_back(Temp);
			g_ModelsMapping[g_DemoNum][I] = g_Models.size();
			
		}
		else
		{
			g_ModelsMapping[g_DemoNum][I] = Ind+1;
		}

		Temp = B.GetString();		
		I++;
	}




	Temp = B.GetString();
	while (Temp.length())
	{
		m_Sounds.push_back(Temp);
		Temp = B.GetString();		
	}
}

void MessageServerinfo::WriteTo(Buffer& B)
{
	B.PutByte(MSG_SERVERINFO);

	B.PutLong(m_Serverversion);
	B.PutByte(m_MaxClients);
	B.PutByte(m_Multi);
	B.PutString(m_MapName);

	std::vector<std::string>::iterator it;

	for (it = g_Models.begin(); it != g_Models.end(); it++)
	{
		B.PutString(*it);		
	}
	B.PutByte(0);
	
	for (it = m_Sounds.begin(); it != m_Sounds.end(); it++)
	{
		B.PutString(*it);		
	}
	B.PutByte(0);

}



MessageClientdata::MessageClientdata(const Buffer& B) : Message(B)
{
	m_Mask = B.GetShort();	

	m_ViewOffsZ = (m_Mask & 0x0001?B.GetByte():22);
	m_PunchangleX = (m_Mask & 0x0002?B.GetByte():0);
	m_Angs[0] = (m_Mask & 0x0004?B.GetByte():0);
	m_Vel[0] = (m_Mask & 0x0020?B.GetByte():0);
	m_Angs[1] = (m_Mask & 0x0008?B.GetByte():0);
	m_Vel[1] = (m_Mask & 0x0040?B.GetByte():0);
	m_Angs[2] = (m_Mask & 0x0010?B.GetByte():0);
	m_Vel[2] = (m_Mask & 0x0080?B.GetByte():0);
	m_Items = B.GetLong();
	m_WeaponFrame = (m_Mask & 0x1000?B.GetByte():0);
	m_ArmorValue = (m_Mask & 0x2000?B.GetByte():0);
	m_WeaponModel = (m_Mask & 0x4000?B.GetByte():0);
	
	m_Health = B.GetShort();
	m_Ammo = B.GetByte();

	for (int I = 0; I < 4; I++)
		m_Ammos[I] = B.GetByte();
	
	if (m_WeaponModel)
		m_WeaponModel = g_ModelsMapping[g_DemoNum][m_WeaponModel];

	g_Weapon = m_Weapon = B.GetByte();
	if (!g_Weapon && m_WeaponModel)
	{
		std::string Model = g_Models[m_WeaponModel-1];
		
		if (Model != "progs/v_axe.mdl")
		{
			if (Model == "progs/v_shot.mdl")
				m_Weapon = g_Weapon = 1;
			else if (Model == "progs/v_shot2.mdl")
				m_Weapon = g_Weapon = 2;
			else if (Model == "progs/v_nail.mdl")
				m_Weapon = g_Weapon = 4;
			else if (Model == "progs/v_nail2.mdl")
				m_Weapon = g_Weapon = 8;
			else if (Model == "progs/v_rock.mdl")
				m_Weapon = g_Weapon = 16;
			else if (Model == "progs/v_rock2.mdl")
				m_Weapon = g_Weapon = 32;
			else if (Model == "progs/v_light.mdl")
				m_Weapon = g_Weapon = 64;
		}
	}
}



void MessageClientdata::WriteTo(Buffer& B)
{
	B.PutByte(MSG_CLIENTDATA);

	if (g_IsRecamming)
		m_Mask &= !(0x0001 |  0x0002 | 0x0020 | 0x0040 | 0x0080 | 0x4000 | 0x1000);
	else
		m_Mask |= (0x0001 |  0x0002 | 0x0020 | 0x0040 | 0x0080 | 0x4000 | 0x1000);
	
	B.PutShort(m_Mask);
	if (m_Mask & 0x0001) B.PutByte(m_ViewOffsZ);
	if (m_Mask & 0x0002) B.PutByte(m_PunchangleX);
	if (m_Mask & 0x0004) B.PutByte(m_Angs[0]);
	if (m_Mask & 0x0020) B.PutByte(m_Vel[0]);
	if (m_Mask & 0x0008) B.PutByte(m_Angs[1]);
	if (m_Mask & 0x0040) B.PutByte(m_Vel[1]);
	if (m_Mask & 0x0010) B.PutByte(m_Angs[2]);
	if (m_Mask & 0x0080) B.PutByte(m_Vel[2]);
	B.PutLong(m_Items);
	if (m_Mask & 0x1000) B.PutByte(m_WeaponFrame);
	if (m_Mask & 0x2000) B.PutByte(m_ArmorValue);
	if (m_Mask & 0x4000) B.PutByte(m_WeaponModel);
	
	B.PutShort(m_Health);
	B.PutByte(m_Ammo);

	for (int I = 0; I < 4; I++)
		B.PutByte(m_Ammos[I]);
	
	B.PutByte(m_Weapon);
}

void MessageClientdata::MergeInto(Block& Other,int ClientNumber)
{
	MessageClientdata* pOtherMessage = Other.GetClientData();
	if (pOtherMessage)
	{
		if (pOtherMessage == (MessageClientdata*)0xcdcdcdcd)
		{
			int X = 0;
		}
		if (pOtherMessage == this)
		{
			m_Ammo = m_ArmorValue = pOtherMessage->m_Health;
			m_Items &= ~(0x00400000 | 0x00200000 | 0x00010000); 
		}

		switch (ClientNumber)
		{
		case 1:
			if (m_Health > 66)
				pOtherMessage->m_Items |= 0x8000;
			else if (m_Health > 33)
				pOtherMessage->m_Items |= 0x4000;
			else
				pOtherMessage->m_Items |= 0x2000;

			pOtherMessage->m_ArmorValue = m_Health;
			pOtherMessage->m_Mask |= 0x2000;
			break;
		case 2:
			pOtherMessage->m_Health = m_Health;
			break;
		case 3:
			pOtherMessage->m_Ammo = m_Health;
			pOtherMessage->m_Items &= ~( 0x00000100 | 0x00000200 | 0x00000400 | 0x00000800);
			if (m_Health > 75)
				pOtherMessage->m_Items |= 0x00000800;
			else if (m_Health > 50)
				pOtherMessage->m_Items |= 0x00000400;
			else if (m_Health > 25)
				pOtherMessage->m_Items |= 0x00000200;
			else
				pOtherMessage->m_Items |= 0x00000100;
		}
	}
}


MessageTempEntity::MessageTempEntity(const Buffer& B) : Message(B)
{
	m_Type = B.GetByte();
	int I;

	if (m_Type == TE_LIGHTNING1 || m_Type == TE_LIGHTNING2 || m_Type == TE_LIGHTNING9)
	{
		m_EntityId = B.GetShort();

		for (I = 0; I < 3;I++)
		{
			m_Coords[I] = B.GetShort();
			m_EndCoords[I] = B.GetShort();;
		}
	}
	else
	{
		m_EntityId = 0;
		for (I = 0; I < 3;I++)
		{
			m_Coords[I] = B.GetShort();
			m_EndCoords[I] = 0;
		}
	}
}

void MessageTempEntity::WriteTo(Buffer& B)
{
	B.PutByte(MSG_TEMPENTITY);

	B.PutByte(m_Type);
	int I;
	if (m_Type == TE_LIGHTNING1 || m_Type == TE_LIGHTNING2 || m_Type == TE_LIGHTNING9)
	{
		B.PutShort(m_EntityId);

		for (I = 0; I < 3;I++)
		{
			B.PutShort(m_Coords[I]);
			B.PutShort(m_EndCoords[I]); 
		}
	}
	else
	{
		for (I = 0; I < 3;I++)
		{
			B.PutShort(m_Coords[I]);
		}
	}
}

extern float m_CameraOrigin[3];
extern float m_CameraAngles[3];
bool SetOrigin = false;


MessageUpdateEntity::MessageUpdateEntity(const Buffer& B,byte ID) : Message(B)
{
	m_Mask = ID & 0x07F;

	if (m_Mask & 0x0001)
	{
		byte temp = B.GetByte();
		m_Mask |= (temp << 8);
	}

	m_EntityId = (m_Mask & 0x4000? B.GetShort():B.GetByte());

	m_Modelindex = (m_Mask & 0x0400 ? B.GetByte():0);

	if (m_Modelindex)
		m_Modelindex = g_ModelsMapping[g_DemoNum][m_Modelindex];

	m_Frame = (m_Mask & 0x0040 ? B.GetByte():0);
	m_Colormap = (m_Mask & 0x0800 ? B.GetByte():0);
	m_Skin = (m_Mask & 0x1000 ? B.GetByte():0);
	m_AttackState = (m_Mask & 0x2000 ? B.GetByte():0);
	
	m_Origin[0] = (m_Mask & 0x0002 ? B.GetShort():0);
	m_Angles[0] = (m_Mask & 0x0100 ? B.GetByte():0);
	m_Origin[1] = (m_Mask & 0x0004 ? B.GetShort():0);
	m_Angles[1] = (m_Mask & 0x0010 ? B.GetByte():0);
	m_Origin[2] = (m_Mask & 0x0008 ? B.GetShort():0);
	m_Angles[2] = (m_Mask & 0x0200 ? B.GetByte():0);

	if (g_IsRecamming && !SetOrigin && m_EntityId == 1)
	{
		for (int I = 0; I < 3; I++)
		{
			m_CameraOrigin[I] = m_Origin[I]* 0.125;
			m_CameraAngles[I] = m_Angles[I]*360.0/256;
		}
		SetOrigin = true;
	}

	if (g_ChangeModels && m_EntityId == g_CurrentEntity )
	{
		int Weapon=-1;
		switch (g_Weapon)
		{
		case 1:		
			Weapon = 0; 
			break;
		case 2:		
			Weapon = 1; 
			break;
		case 4:		
			Weapon = 2; 
			break;
		case 8:		
			Weapon = 3; 
			break;
		case 16:		
			Weapon = 4; 
			break;
		case 32:		
			Weapon = 5; 
			break;
		case 64:		
			Weapon = 6;
			break;
		}

		if (Weapon == -1)
		{
			// it's an exe, if the player's model is not axe - fix it
			if (m_Frame >= 6 && m_Frame <= 12)
				m_Frame -= 6;			
			else if (m_Frame >= 13 && m_Frame <= 17)
				m_Frame += 5;

			m_Mask |= 0x40;
		}
		else if (m_Frame >= 6 && m_Frame <= 16) // rockrun/stand
		{
			m_Modelindex = g_NewModels + Weapon;
			m_Frame -= 6;
		}
		else if (m_Frame >= 35 && m_Frame <= 40) // pain
		{
			m_Modelindex = g_NewModels + Weapon;
			m_Frame -= 24;
		}
		else if (m_Frame >= 103 && m_Frame <= 104) // nailatt
		{
			m_Modelindex = g_NewModels + Weapon;
			m_Frame -= 86;
		}
		else if (m_Frame >= 105 && m_Frame <= 106) // light
		{
			Weapon = 6;
			m_Modelindex = g_NewModels + Weapon;
			m_Frame -= 88;
		}
		else if (m_Frame >= 107 && m_Frame <= 112) // rocket attack
		{
			m_Modelindex = g_NewModels + Weapon;
			m_Frame -= 90;
		}		
		else if (m_Frame >= 113 && m_Frame <= 118) // shotatt
		{
			m_Modelindex = g_NewModels + Weapon;
			m_Frame -= 96;
		}


		if (m_Modelindex)
			m_Mask |= 0x0401;
	}

}

MessageUpdateEntity::MessageUpdateEntity(int EntityId,float Origin[3],float Angles[3])
{
	m_EntityId = EntityId;
	for (int I = 0; I < 3; I++)
	{
		m_Origin[I] = (short)(Origin[I] / 0.125);
		m_Angles[I] = (byte)(Angles[I] * 256 / 360);
	}
	m_Mask = 0x0002 | 0x0100 | 0x0004 | 0x0010 | 0x0008 | 0x0200 | 0x4000 | 0x0001;
}

void MessageUpdateEntity::WriteTo(Buffer& B)
{
	B.PutByte(m_Mask | 0x80);
	
	if (m_Mask & 0x0001)
	{
		byte temp = m_Mask >> 8;
		B.PutByte(temp);
	}

	if (m_Mask & 0x4000) 
		B.PutShort(m_EntityId);
	else
		B.PutByte(m_EntityId);

	if (m_Mask & 0x0400) B.PutByte(m_Modelindex >= 500 ? m_Modelindex-500+g_NewModels:m_Modelindex);
	if (m_Mask & 0x0040) B.PutByte(m_Frame);
	if (m_Mask & 0x0800) B.PutByte(m_Colormap);
	if (m_Mask & 0x1000) B.PutByte(m_Skin);
	if (m_Mask & 0x2000) B.PutByte(m_AttackState);
	
	if (m_Mask & 0x0002) B.PutShort(m_Origin[0]);
	if (m_Mask & 0x0100) B.PutByte(m_Angles[0]);
	if (m_Mask & 0x0004) B.PutShort(m_Origin[1]);
	if (m_Mask & 0x0010) B.PutByte(m_Angles[1]);
	if (m_Mask & 0x0008) B.PutShort(m_Origin[2]);
	if (m_Mask & 0x0200) B.PutByte(m_Angles[2]);
}

void MessageUpdateEntity::RenumberEntity(int OldId, int NewId)
{
	if (m_EntityId == OldId)
		m_EntityId = NewId;
}

void MessageUpdateEntity::ShiftEntity(int Id, int Offset[3])
{
	if (m_EntityId == Id)
	{
		for (int I = 0; I < 3; I++)
			m_Origin[I] += Offset[I];
	}
}

void MessageUpdateEntity::MergeInto(Block& Other,int ClientNumber)
{
	if (g_Intermission)
		return;

	MessageUpdateEntity* pUpd = Other.GetUpdateFor(m_EntityId);
	if (pUpd)
	{
		if (!pUpd->m_Modelindex || m_Modelindex)
			*pUpd = *this;
		else
		{
			int X = 0;
		}
	}
	else 
		Other.AddMessage(Clone());
}

bool MessageUpdateEntity::IsUpdateFor(int EntityId)
{
	return (m_EntityId == EntityId);
}


MessageSetView::MessageSetView(const Buffer& B) : Message(B)
{
	m_EntityId= B.GetShort();
	g_CurrentEntity = m_EntityId;
}
void MessageSetView::WriteTo(Buffer& B)
{
	B.PutByte(MSG_SETVIEW);
	if (g_IsRecamming)
	{
		if (!g_Intermission)
			m_EntityId = 449;
		else
			m_EntityId = 1;
	}
		
	B.PutShort(m_EntityId);
}

MessageSignonUp::MessageSignonUp(const Buffer& B) : Message(B)
{
	m_Signon= B.GetByte();
}
void MessageSignonUp::WriteTo(Buffer& B)
{
	if (g_IsRecamming)
	{
		// spawn the camera
		B.PutByte(MSG_SPAWNBASELINE);
		B.PutShort(449);
		B.PutByte(10); // model = don't care
		B.PutByte(0); // frame
		B.PutByte(0); // colormap
		B.PutByte(0); // skin
		for (int I = 0;I < 3; I++)
		{
			B.PutShort(0); // coord
			B.PutByte(0); // angle
		}

		B.PutByte(MSG_SETVIEW);
		B.PutShort(449);
	}

	B.PutByte(MSG_SIGHNONUP);
	B.PutByte(m_Signon);
}


///////////////////////////////////////
MessageCenterprint::MessageCenterprint(const Buffer& B) : Message(B)
{
	m_Data = B.GetString();
}

void MessageCenterprint::WriteTo(Buffer& B)
{
	B.PutByte(MSG_CENTERPRINT);
	B.PutString(m_Data);
}
///////////////////////////////////////
MessageIntermission::MessageIntermission(const Block& B) : Message(B)
{
	B.SetLast();
}

void MessageIntermission::WriteTo(Buffer& B)
{
	B.PutByte(MSG_INTERMISSION);

	B.PutByte(MSG_SETVIEW);
	B.PutShort(1);
}
///////////////////////////////////////
MessageFinale::MessageFinale(const Block& B) : Message(B)
{
	m_Data = B.GetString();
	B.SetLast();


}

void MessageFinale::WriteTo(Buffer& B)
{
	B.PutByte(MSG_FINALE);
	B.PutString(m_Data);

	B.PutByte(MSG_SETVIEW);
	B.PutShort(1);
}



MessageSpawnBaseLine::MessageSpawnBaseLine(const Buffer& B) : Message(B)
{
	m_EntityId = B.GetShort();

	m_Modelindex =	B.GetByte();
	if (m_Modelindex && m_Modelindex != g_ModelsMapping[g_DemoNum][m_Modelindex])
		m_Modelindex = g_ModelsMapping[g_DemoNum][m_Modelindex];

	m_Frame =		B.GetByte();
	m_Colormap =	B.GetByte();
	m_Skin =		B.GetByte();
	for (int I = 0; I < 3; I++)
	{
		m_Origin[I] = B.GetShort();
		m_Angles[I] = B.GetByte();
	}

}


void MessageSpawnBaseLine::WriteTo(Buffer& B)
{
	B.PutByte(MSG_SPAWNBASELINE);
	B.PutShort(m_EntityId);

	B.PutByte(m_Modelindex);
	B.PutByte(m_Frame);
	B.PutByte(m_Colormap);
	B.PutByte(m_Skin);
	
	for (int I = 0; I < 3; I++)
	{
		B.PutShort(m_Origin[I]);
		B.PutByte(m_Angles[I]);
	}
}

void MessageSpawnBaseLine::RenumberEntity(int OldId, int NewId)
{
	if (m_EntityId == OldId)
		m_EntityId = NewId;
}

void MessageSpawnBaseLine::ShiftEntity(int Id, int Offset[3])
{
	if (m_EntityId == Id)
	{
		for (int I = 0; I < 3; I++)
			m_Origin[I] += Offset[I];
	}
}

void MessageSpawnBaseLine::MergeInto(Block& Other,int ClientNumber)
{
	if (!Other.GetUpdateFor(m_EntityId))
		Other.AddMessage(Clone());		
}

bool MessageSpawnBaseLine::IsUpdateFor(int EntityId)
{
	return (m_EntityId == EntityId);
}
